package com.corecloud.security;

import com.corecloud.config.MyAuthenticationFailHandler;
import com.corecloud.config.MyAuthenticationSuccessHandler;
import com.corecloud.config.mobile.SmsCodeAuthenticationSecurityConfig;
import com.corecloud.controller.sms.SmsCodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

/**
 * 权限验证及登录认证相关配置
 */
@Order(1)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private MyFilterSecurityInterceptor myFilterSecurityInterceptor;

	@Autowired
	private SmsCodeFilter smsCodeFilter;

	/**
	 * 自定义短信登陆成功结果
	 */
	@Autowired
	private MyAuthenticationSuccessHandler authenticationSuccessHandler;

	/**
	 * 自定义短信登陆失败结果
	 */
	@Autowired
	private MyAuthenticationFailHandler authenticationFailHandler;

	/**
	 * 注入短信登录的相关配置
	 */
	@Autowired
	private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

	/**
	 * security相关配置
	 * @param http
	 * @throws Exception
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
				.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
				.authorizeRequests()//配置认证规则
				//可以任意访问
				.antMatchers("/admin/**",
						"/h5SignIn/**",
						"/oauth/**",
						"/edu2ndmaj/**",
						"/authentication/**",
						"/login/**",
						"/static/**",
						"/api/**",
						"/error/**",
						"/user/saveExternalUser",
						"/user/updateExternalUserPwd",
						"/code/**").permitAll()
				// 需要具有ROLE_ADMIN角色才能访问
                .antMatchers("/admin/**").hasAnyRole("ADMIN")
				//除去以上访问其余皆需要认证
				.anyRequest().authenticated()
				;

		//登录
		http
				//使用表单登录，不再使用默认 httpBasic 方式
				.formLogin()
				// 访问需要登录才能访问的页面，如果未登录，会跳转到该地址来
				.loginPage("/authentication/login")
				//登录请求
				.loginProcessingUrl("/login")
				//登录失败跳转页面
//				.failureUrl("/sys/login")//旧版
				.failureUrl("/login/index")
				//默认登录成功路由
				.defaultSuccessUrl("/home/index")
				.successHandler(authenticationSuccessHandler)
				.failureHandler(authenticationFailHandler)
				//允许所有用户访问登录页
				.permitAll()
		;

		//登出
		http
				//退出
				.logout()
				//退出登录路由
//				.logoutUrl("/logout")
				//退出成功后会被重定向到此 URL
//				.logoutSuccessUrl("/sys/login")//旧版
				.logoutSuccessUrl("/login/index")
				//清除缓存
				.invalidateHttpSession(true)
				//在CSRF功能开启的情况下使用GET 去logout
				.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
				//允许所有用户访问
				.permitAll();

		http.apply(smsCodeAuthenticationSecurityConfig);


		//允许项目中引用相同域名下iframe
		http.headers().frameOptions().sameOrigin();

		//关闭 跨域伪造请求限制
		http.csrf().disable();

		//关闭 跨域资源共享限制
		http.cors().disable();

		//禁用httpBasic
		http.httpBasic().disable();

		//配置权限
		http
				.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class)
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class);

	}


	/**
	 * //配置静态文件不需要认证
	 * @param web
	 * @throws Exception
	 */
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/static/**");
	}


	/**
	 * 用户数据源-自定义验证
	 * @param auth
	 * @throws Exception
	 */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService);
		super.configure(auth);
	}


	@Override
	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

}
